#include "rtsp.h"
#include <sstream>

using namespace VLRTSP;

namespace VLRTSP {

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 15:16:11
 * 
 * RTSP 指令结构体
 */
struct RTSPCommand {
	/**
	 * @Author: CimZzz
	 * @Date: 2022-01-13 15:21:01
	 * 
	 * 指令码
	 */
	enum TypeCode {
		RemoveConnection
	};

	/**
	 * @Author: CimZzz
	 * @Date: 2022-01-13 15:16:44
	 * 
	 * 构造函数
	 * @param code 指令码
	 * @param number 数字参数
	 * @param callback 指令回调函数
	 */
	RTSPCommand(TypeCode code, uint32_t number, std::shared_ptr<void> data): data(data) {
		this->code = code;
		this->number = number;
	}

	RTSPCommand(TypeCode code, uint32_t number): data(nullptr) {
		this->code = code;
		this->number = number;
	}

	TypeCode code;
	uint32_t number;
	std::shared_ptr<void> data;
};


}

/**
 * @Author: CimZzz
 * @Date: 2022-01-11 11:58:15
 * 
 * 快捷上锁宏定义
 */
#define _RTSP_LOCK std::lock_guard<std::recursive_mutex> lock(this->mutex);

/**
 * @Author: CimZzz
 * @Date: 2022-01-07 10:22:07
 * 
 * 显示构造器
 * @param port 监听端口
 * @param statusCallback 状态回调函数
 */
RTSPServer::RTSPServer(uint16_t port, StatusCallback statusCallback): 
	tcpServer(port),
	commandThread([this](std::shared_ptr<RTSPCommand> command) {
		this->_onRecvCommand(command);
	}) {
	this->port = port;
	this->statusCallback = statusCallback;
	this->status = RTSPServerStatus::Stopped;
	this->tcpServer.setServerStartCallback([this] {
		this->_onServerStart();
	});
	this->tcpServer.setServerDoneCallback([this] {
		this->_onServerDone();
	});
	this->tcpServer.setRecvSocketCallback([this] (std::shared_ptr<TCPSocket> socket) {
		this->_onRecvSocket(socket);
	});
	this->commandThread.start();
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-11 10:44:02
 * 
 * 析构函数
 */
RTSPServer::~RTSPServer() {
	this->destroy();
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 19:48:50
 * 
 * 添加新的媒体会话
 * @param session 媒体会话指针
 */
void RTSPServer::addMediaSession(MediaSession* session) {
	_RTSP_LOCK
	if(this->status == RTSPServerStatus::Destroyed) {
		// 状态不符
		delete session;
		return;
	}
	this->context._addMediaSession(session);
	session->_attachRTSPServer(&this->context);
}



/**
 * @Author: CimZzz
 * @Date: 2022-01-14 19:08:21
 * 
 * 推送媒体资源数据
 * @param sessionId 媒体会话 Id
 * @param sourceId 资源 Id
 * @param data 媒体资源数据
 */
void RTSPServer::pushMediaData(const std::string& sessionId, uint32_t sourceId, MediaSourceData* data) {
	if(this->status != RTSPServerStatus::Running) {
		// 非法推送状态
		delete data;
		return;
	}
	MediaSource* source = this->context._findMediaSource(sessionId, sourceId);
	if(source == nullptr) {
		delete data;
		return;
	}
	source->sendFrame(data);
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-07 10:23:21
 * 
 * 启动 RTSP 服务器
 */
void RTSPServer::start() {
	_RTSP_LOCK
	if(this->status != RTSPServerStatus::Stopped) {
		// 非法启动状态
		return;
	}
	this->_changeStatus(RTSPServerStatus::Bootsrap);
	this->tcpServer.start();
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-07 10:24:24
 * 
 * 回收 RTSP 服务器
 */
void RTSPServer::destroy() {
	_RTSP_LOCK
	if(this->status == RTSPServerStatus::Destroyed) {
		return;
	}
	this->status = RTSPServerStatus::Destroyed;
	
	this->tcpServer.destroy();
	this->commandThread.destroy();
	this->context._destroy();
	this->_changeStatus(RTSPServerStatus::Destroyed);
}

/**
 * +======================================================================================================================+
 * @Author: CimZzz
 * @Date: 2022-01-11 11:06:30
 * 
 * 代码分割块，以下内容涉及: 
 * 
 * 内部方法
 * 
 */



/**
 * @Author: CimZzz
 * @Date: 2022-01-13 10:57:10
 * 
 * TCP 服务器启动回调函数
 */
void RTSPServer::_onServerStart() {
	_RTSP_LOCK
	if(this->status != RTSPServerStatus::Bootsrap) {
		return;
	}
	std::stringstream stream;
	stream << "rtsp://0.0.0.0:" << this->port;
	this->_changeStatus(RTSPServerStatus::Running, new std::string(stream.str()));
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 10:57:23
 * 
 * TCP 服务器结束回调函数
 */
void RTSPServer::_onServerDone() {
	_RTSP_LOCK
	if(this->status == RTSPServerStatus::Bootsrap) {
		// 启动过程中关闭，认做启动失败
		this->_changeStatus(RTSPServerStatus::Error, new std::string("TCP Server bootstrap failure"));
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 10:57:46
 * 
 * 接收到 Socket 回调函数
 */
void RTSPServer::_onRecvSocket(std::shared_ptr<TCPSocket>& socket) {
	TCPSocket* socketPtr = socket.get();
	if(socketPtr != nullptr) {
		_RTSP_LOCK
		if(this->status == RTSPServerStatus::Running) {
			uint32_t id = syncCode.nextCode();
			std::shared_ptr<RTSPConnection> connection(new RTSPConnection(
				id,
				&this->context,
				socket
			));
			bool isSuccess = connection.get()->addCloseCallback([this](uint32_t connectionId, std::shared_ptr<std::string> msg) {
				VL_LOG("RTSPServer", "移除 RTSPConnection: %d", connectionId)
				this->commandThread.send(new RTSPCommand(RTSPCommand::RemoveConnection, connectionId));
			});
			if(isSuccess) {
				VL_LOG("RTSPServer", "新增 RTSPConnection: %d", id);
				this->context._addRTSPConnection(connection);
			}
		}
		else {
			socket->close();
		}
	}
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-13 14:55:50
 * 
 * 接收到 RTSP 消息队列指令
 * @param command RTSP 指令
 */
void RTSPServer::_onRecvCommand(std::shared_ptr<RTSPCommand>& command) {
	RTSPCommand* commandPtr = command.get();
	if(commandPtr == nullptr) {
		return;
	}
	switch (commandPtr->code) {
		case RTSPCommand::RemoveConnection: {
			uint32_t connectionId = commandPtr->number;
			this->context._removeRTSPConnection(connectionId);
		}
		break;
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-11 11:07:37
 * 
 * 切换当前 RTSP 服务器状态
 * @param status 服务器状态
 * @param message 状态消息
 */
void RTSPServer::_changeStatus(RTSPServerStatus status, std::string* message) {
	this->status = status;
	_RTSP_LOCK
	if(this->statusCallback) {
		this->statusCallback(status, std::shared_ptr<std::string>(message));
	} else if(message != nullptr) {
		delete message;
	}
}